home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 23
/
AACD 23.iso
/
AACD
/
Online
/
opennap
/
util.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-08
|
10KB
|
477 lines
/* Copyright (C) 2000-1 drscholl@users.sourceforge.net
This is free software distributed under the terms of the
GNU Public License. See the file COPYING for details.
$Id: util.c,v 1.98 2001/02/15 08:39:45 drscholl Exp $
This file contains various utility functions useful elsewhere in this
server */
/* Modified 29/05/01 : init_random() modified to remove dependency on the
for Amiga port : structure "global", which doesn't exist in Amiga GCC
2.7.0
*/
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#ifndef WIN32
#include <unistd.h>
#include <sys/time.h>
#endif
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "md5.h"
#include "opennap.h"
#include "debug.h"
/* writes `val' as a two-byte value in little-endian format */
void
set_val (char *d, unsigned short val)
{
val = BSWAP16 (val);
memcpy (d, &val, 2);
}
/* this is like strtok(2), except that all fields are returned as once. nul
bytes are written into `pkt' and `template' is updated with pointers to
each field in `pkt' */
/* returns: number of fields found. */
int
split_line (char **template, int templatecount, char *pkt)
{
int i = 0;
if (!pkt)
return -1;
while (ISSPACE (*pkt))
pkt++;
while (*pkt && i < templatecount)
{
if (*pkt == '"')
{
/* quoted string */
pkt++;
template[i++] = pkt;
pkt = strchr (pkt, '"');
if (!pkt)
{
/* bogus line */
return -1;
}
*pkt++ = 0;
if (!*pkt)
break;
pkt++; /* skip the space */
}
else
{
template[i++] = pkt;
pkt = strpbrk (pkt, " \t\r\n");
if (!pkt)
break;
*pkt++ = 0;
}
while (ISSPACE (*pkt))
pkt++;
}
return i;
}
static char hex[] = "0123456789ABCDEF";
void
expand_hex (char *v, int vsize)
{
int i;
for (i = vsize - 1; i >= 0; i--)
{
v[2 * i + 1] = hex[v[i] & 0xf];
v[2 * i] = hex[(v[i] >> 4) & 0xf];
}
}
void
init_random (void)
{
/*ASSERT (global.current_time != 0);*/
/* force generation of a different seed if respawning quickly by adding
the pid of the current process */
srand (/*global.current_time + */time(NULL) + getuid () + getpid ());
}
void
get_random_bytes (char *d, int dsize)
{
int i = 0, v;
while (i < dsize)
{
v = rand ();
d[i++] = v & 0xff;
if (i < dsize)
d[i++] = (v >> 8) & 0xff;
if (i < dsize)
d[i++] = (v >> 16) & 0xff;
if (i < dsize)
d[i++] = (v >> 24) & 0xff;
}
}
/* generate our own nonce value */
char *
generate_nonce (void)
{
char *nonce;
nonce = MALLOC (17);
if (!nonce)
{
OUTOFMEMORY ("generate_nonce");
return 0;
}
nonce[16] = 0;
get_random_bytes (nonce, 8);
/* expand the binary data into hex for transport */
expand_hex (nonce, 8);
return nonce;
}
CHANNEL *
new_channel (void)
{
CHANNEL *c = CALLOC (1, sizeof (CHANNEL));
if (!c)
{
OUTOFMEMORY ("new_channel");
return 0;
}
#ifdef DEBUG
c->magic = MAGIC_CHANNEL;
#endif
return c;
}
char *
strfcpy (char *dest, const char *src, size_t destlen)
{
strncpy (dest, src, destlen);
dest[destlen - 1] = 0;
return dest;
}
#if LOG_CHANNEL
static int Logging = 0;
#endif
void
log (const char *fmt, ...)
{
va_list ap;
#if LOG_CHANNEL
char buf[1024];
int len;
char *msg;
strfcpy (buf + 4, "&LOG opennap ", sizeof (buf) - 4);
len = strlen (buf + 4);
msg = buf + len + 4;
va_start (ap, fmt);
vsnprintf (buf + 4 + len, sizeof (buf) - 4 - len, fmt, ap);
va_end (ap);
/* prevent infinite loop */
if (!Logging)
{
len += strlen (buf + 4 + len);
set_tag (buf, MSG_SERVER_PUBLIC);
set_len (buf, len);
Logging = 1;
(void) send_to_channel ("&LOG", buf, len + 4);
Logging = 0;
}
/* display log msg on console */
fputs (msg, stdout);
#else
va_start (ap, fmt);
vprintf (fmt, ap);
va_end (ap);
#endif
fputc ('\n', stdout);
fflush (stdout);
}
/* like next_arg(), except we don't skip over additional whitespace */
char *
next_arg_noskip (char **s)
{
char *r = *s;
*s = strchr (r, ' ');
if (*s)
*(*s)++ = 0;
return r;
}
char *
next_arg (char **s)
{
char *r = *s;
if (!r)
return 0;
while (ISSPACE (*r))
r++;
if (!*r)
return 0;
if (*r == '"')
{
r++;
*s = strchr (r, '"');
}
else
*s = strpbrk (r, " \t\r\n");
if (*s)
{
*(*s)++ = 0;
while (ISSPACE (**s))
++ * s;
if (!**s)
*s = 0; /* no more arguments */
}
return r;
}
char *
strlower (char *s)
{
char *r = s;
ASSERT (s != 0);
while (*s)
*s++ = tolower ((unsigned char) *s);
return r;
}
int
safe_realloc (void **ptr, int bytes)
{
void *t;
t = REALLOC (*ptr, bytes);
if (!t)
return -1;
*ptr = t;
return 0;
}
void
print_args (int ac, char **av)
{
int i;
printf ("print_args(): [%d]", ac);
for (i = 0; i < ac; i++)
printf (" \"%s\"", av[i]);
fputc ('\n', stdout);
}
static char alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define alphabet(c) alphabet[(unsigned int)c]
static int
b64_encode (char *out, int *outsize, char *in, int insize)
{
unsigned char a, b, c, d;
char *pout = out;
while (insize > 0)
{
c = d = 0xff;
a = (*in >> 2) & 0x3f;
b = (*in & 0x3) << 4;
in++;
insize--;
if (insize)
{
b |= (*in >> 4) & 0xf;
c = (*in & 0xf) << 2;
in++;
insize--;
if (insize)
{
c |= (*in >> 6) & 0x3;
d = *in & 0x3f;
in++;
insize--;
}
}
*out++ = alphabet (a);
*out++ = alphabet (b);
if (c != 0xff)
{
*out++ = alphabet (c);
if (d != 0xff)
*out++ = alphabet (d);
else
*out++ = '=';
}
else
{
*out++ = '=';
*out++ = '=';
}
}
*out = 0;
*outsize = out - pout;
return 0;
}
static char b64_lookup[128] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
};
#define b64_lookup(c) b64_lookup[(unsigned int)c]
static int
b64_decode (char *out, int *outsize, const char *in)
{
unsigned char a, b, c, d;
unsigned char b2, b3;
char *pout = out;
while (*in)
{
a = b64_lookup (*in++);
b = b64_lookup (*in++);
*out++ = a << 2 | b >> 4;
b2 = b << 4;
if (*in && *in != '=')
{
c = b64_lookup (*in++);
b2 |= c >> 2;
*out++ = b2;
b3 = c << 6;
if (*in && *in != '=')
{
d = b64_lookup (*in++);
b3 |= d;
*out++ = b3;
}
else
break;
}
else
break;
}
*outsize = out - pout;
return 0;
}
int
check_pass (const char *info, const char *pass)
{
struct md5_ctx md;
char hash[16], real[16];
int realsize;
ASSERT (info != 0);
ASSERT (pass != 0);
if (*info != '1' || *(info + 1) != ',')
return -1;
info += 2;
md5_init_ctx (&md);
md5_process_bytes (info, 8, &md);
info += 8;
if (*info != ',')
return -1;
info++;
md5_process_bytes (pass, strlen (pass), &md);
md5_finish_ctx (&md, hash);
realsize = sizeof (real);
b64_decode (real, &realsize, info);
ASSERT (realsize == 16);
if (memcmp (real, hash, 16) == 0)
return 0;
return -1;
}
char *
generate_pass (const char *pass)
{
struct md5_ctx md;
char hash[16];
char output[36]; /* 1,xxxxxxxx,xxxxxxxxxxxxxxxxxxxxxxx== */
int outsize;
int i;
ASSERT (pass != 0);
output[0] = '1';
output[1] = ',';
get_random_bytes (output + 2, 8);
for (i = 0; i < 8; i++)
output[i + 2] = alphabet[((unsigned int) output[i + 2]) % 64];
output[10] = ',';
md5_init_ctx (&md);
md5_process_bytes (output + 2, 8, &md);
md5_process_bytes (pass, strlen (pass), &md);
md5_finish_ctx (&md, hash);
outsize = sizeof (output) - 11;
b64_encode (output + 11, &outsize, hash, 16);
output[sizeof (output) - 3] = 0; /* strip the trailing == */
return (STRDUP (output));
}
CHANNEL *
find_channel (LIST * channels, const char *s)
{
for (; channels; channels = channels->next)
if (!strcasecmp (((CHANNEL *) channels->data)->name, s))
return channels->data;
return 0;
}
void
free_pointer (void *p)
{
FREE (p);
}
/* check to make sure this string is a valid host name. include the glob
* characters
*/
int
invalid_host (const char *p)
{
while (*p)
{
if (!isalnum (*p) || !strchr (".-?*", *p))
return 1;
p++;
}
return 0;
}